package com.yidian.task;

import com.alibaba.fastjson.JSON;
import com.yidian.dao.SeckillGoodsMapper;
import com.yidian.pojo.seckill.SeckillGoods;
import com.yidian.pojo.seckill.SeckillOrder;
import com.yidian.pojo.seckill.SeckillStatus;
import com.yidian.utils.IdWorkerBySnowFlake;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * @author whb
 * @create 2021-10-25 14:44
 * @desciption Spring多线程异步操作类
 */
@Component
public class MultiThreadingCreateOrder {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private IdWorkerBySnowFlake idWorkerBySnowFlake;
    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Async
    public void createOrder() {
        SeckillStatus seckillStatus = (SeckillStatus) redisTemplate.boundListOps("SeckillOrderQueue").rightPop();//从秒杀信息队列中读取秒杀信息
        try {
            System.out.println("----准备@Async执行----");
            Thread.sleep(10000);

            Object goodId = redisTemplate.boundListOps("SeckillGoodsCountList_" + seckillStatus.getGoodsId()).rightPop();//从库存数量队列中读取商品id
            if (goodId==null){
                clearQueue(seckillStatus);//清除队列信息，否则不能再继续参与秒杀
                return;
            }

            Long id = seckillStatus.getGoodsId();
            String time = seckillStatus.getTime();
            String username = seckillStatus.getUsername();

            SeckillGoods seckillGoods = (SeckillGoods) redisTemplate.boundHashOps("SeckillGoods_" + time).get(id);//查询商品详情
            if (seckillGoods != null && seckillGoods.getStockCount() > 0) {
                SeckillOrder seckillOrder = new SeckillOrder();//创建订单
                seckillOrder.setId(idWorkerBySnowFlake.nextId());//设置订单ID
                seckillOrder.setSeckillId(id);//秒杀商品ID
                seckillOrder.setMoney(seckillGoods.getCostPrice());//支付金额
                seckillOrder.setUserId(username);//用户名
                seckillOrder.setSellerId(seckillGoods.getSellerId());//商家用户名
                seckillOrder.setCreateTime(new Date());//订单创建时间
                seckillOrder.setStatus("0");//支付状态，0：未支付，1：已支付
                redisTemplate.boundHashOps("SeckillOrder").put(username, seckillOrder);//将订单存入到redis缓存中

                //seckillGoods.setStockCount(seckillGoods.getStockCount() - 1);//库存削减
                Long surplusCount = redisTemplate.boundHashOps("SeckillGoodsCount").increment(id, -1);//redis自增increment是单线程，不会出现线程安全问题
                seckillGoods.setStockCount(surplusCount.intValue());//削减库存
                //if (seckillGoods.getStockCount() <= 0) {
                if (surplusCount <= 0) {
                    seckillGoodsMapper.updateByPrimaryKeySelective(seckillGoods);//更新秒杀商品信息
                    redisTemplate.boundHashOps("SeckillGoods_" + time).delete(id);//商品库存已售罄，将商品从redis缓存中清除
                } else {
                    redisTemplate.boundHashOps("SeckillGoods_" + time).put(id, seckillGoods);//更新redis缓存
                }

                //更新秒杀信息
                seckillStatus.setOrderId(seckillOrder.getId());//设置订单ID
                seckillStatus.setMoney(seckillOrder.getMoney().floatValue());//设置秒杀价格
                seckillStatus.setStatus(2);//秒杀成功，待支付
                redisTemplate.boundHashOps("UserQueueStatus").put(username, seckillStatus);//将更新秒杀信息存入到redis缓存
            }

            sendDelayMessage(seckillStatus);//返送超时支付的rabbitmq延时消息

            System.out.println("开始执行");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 清楚用户排队队列信息
     * @param seckillStatus 秒杀信息状态对象
     */
    private void clearQueue(SeckillStatus seckillStatus) {
        redisTemplate.boundHashOps("UserQueueCount").delete(seckillStatus.getUsername());//清除登录用户重复排队标识，可以继续参与秒杀抢单
        redisTemplate.boundHashOps("UserQueueStatus").delete(seckillStatus.getUsername());//清除秒杀信息状态队列
    }

    /**
     * 延时消息发送
     * @param seckillStatus 秒杀状态信息
     */
    private void sendDelayMessage(SeckillStatus seckillStatus) {
        rabbitTemplate.convertAndSend("exchange.delay.order.begin", "delay", JSON.toJSONString(seckillStatus), new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                message.getMessageProperties().setExpiration(String.valueOf(10000));
                return message;
            }
        });
    }
}
